package net.jcip.examples.chapter6;

import java.util.*;
import java.util.concurrent.*;

/**
 * QuoteTask
 * <p/>
 * Requesting travel quotes under a time budget
 *
 * ## Java 中 invokeAll  用于并发执行任务并带有超时的代码解释
 *
 * 该代码片段描述了 Java 中一种用于并发执行任务并带有超时的的方法。以下是详细解释：
 *
 * **功能:**
 *
 * * 此方法并发执行给定集合中的任务。
 * * 它返回一个 `Future` 对象列表。这些 `Future` 对象表示任务的状态和结果。
 * * 该方法会等待任务完成或指定超时时间到期，以先到为准。
 *
 * **返回值:**
 *
 * * 该方法返回一个 `Future` 对象列表。
 * * 每个 `Future` 对象都对应原始集合中的一个任务。
 * * 通过调用 `Future` 对象上的 `isDone()` 方法，您可以检查相应的任务是否已完成。
 * * 如果方法在所有任务完成之前超时，则会取消未完成的任务。
 *
 * **参数:**
 *
 * * `tasks`: 这是一组要并发执行的任务。
 * * `timeout`: 这是等待任务完成的最大时间。
 * * `unit`: 这是 `timeout` 参数的时间单位（例如，毫秒、秒）。
 *
 * **异常:**
 *
 * * `InterruptedException`: 如果等待过程被中断（例如，由另一个线程），则会抛出此异常。在这种情况下，未完成的任务将被取消。
 * * `NullPointerException`: 如果以下任何一项为空，则会抛出此异常：`tasks` 集合、`tasks` 集合中的任何元素或 `unit` 参数。
 * * `RejectedExecutionException`: 如果任何任务无法安排执行（例如，由于资源限制），则会抛出此异常。
 *
 * **其他注意事项:**
 *
 * * 返回列表中 `Future` 对象的顺序与原始集合中任务的顺序匹配。
 * * 如果任务在超时之前完成，所有 `Future` 对象都将指示已完成的任务。
 * * 如果方法在所有任务完成之前超时，则一些 `Future` 对象可能代表未完成的任务。
 *
 * **简单来说：**
 *
 * 此方法允许您在指定时间限制内同时运行多个任务。它会给您一个对象列表，这些对象会告诉您这些任务的状态和结果（已完成或未完成）。它会在时间限制到期时取消任何未完成的任务。
 * @author Brian Goetz and Tim Peierls
 */
public class TimeBudget {
    private static ExecutorService exec = Executors.newCachedThreadPool();

    public List<TravelQuote> getRankedTravelQuotes(TravelInfo travelInfo, Set<TravelCompany> companies,
                                                   Comparator<TravelQuote> ranking, long time, TimeUnit unit)
            throws InterruptedException {
        List<QuoteTask> tasks = new ArrayList<>();
        for (TravelCompany company : companies)
            tasks.add(new QuoteTask(company, travelInfo));

        List<Future<TravelQuote>> futures = exec.invokeAll(tasks, time, unit);

        List<TravelQuote> quotes = new ArrayList<>(tasks.size());
        Iterator<QuoteTask> taskIter = tasks.iterator();
        for (Future<TravelQuote> f : futures) {
            QuoteTask task = taskIter.next();
            try {
                quotes.add(f.get());
            } catch (ExecutionException e) {
                quotes.add(task.getFailureQuote(e.getCause()));
            } catch (CancellationException e) {
                quotes.add(task.getTimeoutQuote(e));
            }
        }

        Collections.sort(quotes, ranking);
        return quotes;
    }

}

/**
 *
 */
class QuoteTask implements Callable<TravelQuote> {
    private final TravelCompany company;
    private final TravelInfo travelInfo;

    public QuoteTask(TravelCompany company, TravelInfo travelInfo) {
        this.company = company;
        this.travelInfo = travelInfo;
    }

    TravelQuote getFailureQuote(Throwable t) {
        return null;
    }

    TravelQuote getTimeoutQuote(CancellationException e) {
        return null;
    }

    public TravelQuote call() throws Exception {
        return company.solicitQuote(travelInfo);
    }
}

interface TravelCompany {
    TravelQuote solicitQuote(TravelInfo travelInfo) throws Exception;
}

interface TravelQuote {
}

interface TravelInfo {
}

